package org.voidness.oje2d;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;

/** A font to draw text on-screen using bitmap fonts. */
public class GLFont {
    /** The font's texture */
    private GLTexture texture = null;

    /** The GL list to hold the characters */
    private int base;

    /** The character iterator */
    private int loop;

    /** The screen's height */
    private int screenHeight;

    /** The zoom with which to draw */
    private float zoom;

    /** The size of the characters */
    private int charSize;

    /**
     * Default font constructor.
     * 
     * @param mFilename The path for the bitmap font to load
     * @param mZoom The zoom factor to apply while drawing
     */
    public GLFont(String mFilename, float mZoom) {
        screenHeight = Display.getDisplayMode().getHeight();
        texture = new GLTexture(mFilename, false);
        zoom = mZoom;
        generateFont();
    }

    /**
     * Destroy the font. Delete the GL list.
     */
    public void destroy() {
        GL11.glDeleteLists(base, 256);
    }

    /**
     * (Re)define the zoom factor.
     * 
     * @param mZoom The zoom factor to apply (0.0f - inf).
     */
    public void setZoom(float mZoom) {
        zoom = mZoom;
        charSize = (int) (16 * zoom);
    }

    /**
     * Print a given string using the font.
     * 
     * @param mText The text to print
     * @param mX The X position where to print
     * @param mY The Y position where to print
     * @param mZoom The zoom factor to use
     * @param mColor The color of the text
     */
    public void print(String mText, int mX, int mY, float mZoom, GLColor mColor) {
        mColor.set();

        setZoom(mZoom);

        GL11.glEnable(GL11.GL_TEXTURE_2D);
        // GL11.glDisable(GL11.GL_LIGHTING);

        // int tmp = 0;
        int set = 0;

        texture.bind();

        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_BLEND);

        GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
        GL11.glPushMatrix(); // Store The Projection Matrix
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 800, 0, 600, -1, 1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();
        GL11.glTranslatef(mX, screenHeight - mY, 0);
        GL11.glScalef(zoom, zoom, 1.0f);
        GL11.glListBase(base - 32 + (128 * set));
        // GL11.glCallLists(ByteBuffer.wrap(text.getBytes()));
        for (int i = 0; i < mText.length(); i++) {
            GL11.glCallList(base - 32 + mText.charAt(i));
            GL11.glTranslatef(1.0f, 0.0f, 0.0f);
        }
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPopMatrix();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPopMatrix();

        GL11.glDisable(GL11.GL_BLEND);
        // gl.glLoadIdentity();

        GL11.glDisable(GL11.GL_TEXTURE_2D);
        // GL11.glEnable(GL11.GL_LIGHTING);

        mColor.reset();
    }

    /**
     * Generates the font from the texture applied.
     */
    public void generateFont() {
        // character coords
        float cx;
        float cy;

        base = GL11.glGenLists(256);

        texture.bind();

        for (loop = 0; loop < 256; loop++) {
            cx = ((float) (loop % 16)) / 16; // X Position Of Current Character
            cy = ((float) (loop / 16)) / 16; // Y Position Of Current Character
            GL11.glNewList(base + loop, GL11.GL_COMPILE);
            GL11.glBegin(GL11.GL_QUADS);
            /*
             * GL11.glTexCoord2f(cx, 1.0f - cy - 0.0625f); GL11.glVertex2i(0,
             * 0); GL11.glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.0625f);
             * GL11.glVertex2i(16, 0); GL11.glTexCoord2f(cx + 0.0625f, 1.0f - cy
             * - 0.001f); GL11.glVertex2i(16, 16); GL11.glTexCoord2f(cx, 1.0f -
             * cy - 0.001f); GL11.glVertex2i(0, 16);
             */

            GL11.glTexCoord2f(cx, 1.0f - cy - 0.0625f);
            GL11.glVertex2i(0, -16);
            GL11.glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.0625f);
            GL11.glVertex2i(16, -16);
            GL11.glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.001f);
            GL11.glVertex2i(16, 0);
            GL11.glTexCoord2f(cx, 1.0f - cy - 0.001f);
            GL11.glVertex2i(0, 0);

            GL11.glEnd(); // Done Building Our Quad (Character)
            GL11.glTranslatef(14, 0, 0); // Move To The Right Of The Character
            GL11.glEndList();
        }

        charSize = (int) (16 * zoom);
    }

    /**
     * Get the size of the characters.
     * 
     * @return The character size
     */
    public int getCharSize() {
        return charSize;
    }
}